<template>
  <el-container class="design-container">
    <el-aside class="design-left-aside" width="25%">
      <el-scrollbar class="left-scrollbar">
        <div class="components-list">
          <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
            <div class="components-title">{{item.title}}</div>
            <draggable class="components-draggable" :list="item.list" :group="{name: 'componentsGroup', pull: 'clone', put: false}" :clone="cloneComponent"
                       draggable=".components-item" :sort="false" @end="onEnd">
              <template #item="{element}">
                <div class="components-item" @click="addComponent(element)">
                  <div class="components-body">{{element.__config__.label}}</div>
                </div>
              </template>
            </draggable>
          </div>
        </div>
      </el-scrollbar>
    </el-aside>
    <el-main class="center-board" style="padding: 0">
      <div class="design-header">
        <div class="design-header-title">{{pageTitle}}</div>
        <div class="action-bar" style="display: inline-block; float: right">
          <el-button type="text" icon="el-icon-save" @click="save">保存</el-button>
          <el-button type="text" icon="el-icon-download" @click="downloadCode">导出Vue</el-button>
          <el-button type="text" icon="el-icon-delete" @click="handleClear">清空</el-button>
        </div>
      </div>
      <el-row class="center-board-row">
        <el-form style="width: 100%" :label-position="formConf.labelPosition" :disabled="formConf.disabled" :label-width="formConf.labelWidth + 'px'">
          <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
            <template #item="{element, index}">
              <draggable-item :key="element.renderKey" :drawing-list="drawingList" :current-item="element" :index="index" :active-id="activeId"
                              :form-conf="formConf" @activeItem="activeFormItem" @copyItem="drawingItemCopy" @deleteItem="drawingItemDelete"/>
            </template>
          </draggable>
          <div v-show="!drawingList.length" class="empty-info">
            请从左侧拖入组件
          </div>
        </el-form>
      </el-row>
    </el-main>
    <el-aside class="design-right-aside" width="25%">
      <right-panel :active-data="activeData" :form-conf="formConf" :show-field="!!drawingList.length"/>
    </el-aside>
  </el-container>
</template>

<script>
import draggable from 'vuedraggable'
import {inputComponents, actionComponents, pageComponents, formConf} from "@/components/generator/config.ts";
import {cloneDeep} from "lodash";
import DraggableItem from "@/components/DraggableItem.vue";
import {reactive, ref} from "vue";
import RightPanel from "@/views/RightPanel.vue";
import {usePageStore} from "@/store/usePageStore.ts";
import {
  makeUpHtml, vueTemplate, vueScript, cssStyle
} from '@/components/generator/html'
import { makeUpJs } from '@/components/generator/js'
import { makeUpCss } from '@/components/generator/css'
import { saveAs } from 'file-saver'

export default {
  name: 'Design',
  components: {
    RightPanel,
    DraggableItem,
    draggable,
  },
  data() {
    return {
      formConf,
      inputComponents,
      actionComponents,
      pageComponents,
      leftComponents: [
        {title: '表单输入', list: inputComponents},
        {title: '操作', list: actionComponents},
        {title: '整体页面组件', list: pageComponents},
      ],
      activeData: reactive({
        __config__: {}
      }),
      drawingList: ref([]),
      activeId: '',
      pageTitle: '',
      formData: {},
      generateConf: null,
    }
  },
  watch: {
    drawingList: {
      handler(val) {
        console.log('drawingList', JSON.parse(JSON.stringify(val)))
      },
      immediate: true,
      deep: true,
    },
    "$route.query.id": {
      handler(val) {
        console.log(val)
        if (val) {
          let page = usePageStore().getPageDetail(val)
          if (page) {
            this.pageTitle = page.title
            Object.keys(page.json || {}).forEach(key => {
              if (key === 'fields') {
                this.drawingList = cloneDeep(page.json?.fields)
              } else {
                this.formConf[key] = page.json[key]
              }
            })
          }
        }
      },
      immediate: true,
    }
  },
  methods: {
    activeFormItem(currentItem) {
      console.log('active')
      this.activeData = currentItem
      this.activeId = currentItem.__config__.formId
    },
    onEnd(obj) {
      if (obj.from !== obj.to) {
        let item = obj.item.__draggable_context.element
        // this.activeFormItem(item)
      }
    },
    addComponent(item) {
      console.log('add')
      const clone = this.cloneComponent(item)
      this.drawingList.push(clone)
      this.activeFormItem(clone)
    },
    cloneComponent(origin) {
      console.log('cloneComponent')
      const clone = cloneDeep(origin)
      const config = clone.__config__
      config.span = this.formConf.span // 生成代码时，会根据span做精简判断
      this.createIdAndKey(clone)
      clone.placeholder !== undefined && (clone.placeholder += config.label)
      return clone
    },
    createIdAndKey(item) {
      const config = item.__config__
      config.formId = Date.now()
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
      item.__vModel__ = `field${Date.now()}`

      if (Array.isArray(config.children)) {
        config.children = config.children.map(childItem => this.createIdAndKey(childItem))
      }
      return item
    },
    AssembleFormData() {
      this.formData = {
        fields: cloneDeep(this.drawingList),
        ...this.formConf
      }
    },
    drawingItemCopy(item, list) {
      let clone = cloneDeep(item)
      clone = this.createIdAndKey(clone)
      list.push(clone)
      this.activeFormItem(clone)
    },
    drawingItemDelete(index, list) {
      list.splice(index, 1)
      this.$nextTick(() => {
        const len = this.drawingList.length
        if (len) {
          this.activeFormItem(this.drawingList[len - 1])
        }
      })
    },
    handleClear() {
      this.$confirm('是否清空所有内容?', '提示', {
        type: "warning"
      }).then(() => {
        this.drawingList = []
        this.activeData = {__config__: {}};
      })
    },
    save() {
      this.AssembleFormData()
      usePageStore().savePage(this.$route.query.id, this.formData)
    },
    generateCode() {
      let type = 'file'
      this.AssembleFormData()
      const script = vueScript(makeUpJs(this.formData, type))
      const html = vueTemplate(makeUpHtml(this.formData, type))
      const css = cssStyle(makeUpCss(this.formData))
      return html + '\n' + script + '\n' + css
      // return beautifier.html(html + script + css, beautifierConf.html)
    },
    downloadCode() {
      const codeStr = this.generateCode()
      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
      saveAs(blob, `${this.pageTitle}_file${Date.now()}.vue`)
    }
  }
}
</script>

<style scoped>
.design-container {
  width: 100%;
  height: 100%;
}
.design-left-aside {
  height: 100%;
  border-right: solid 1px #ddd;
}
.design-right-aside {
  height: 100%;
  border-left: solid 1px #ddd;
}
.design-header-title {
  display: inline-block;
}
.design-header {
  height: 40px;
  width: 100%;
}
</style>
